const Browser = require("./Browser");

/**
 * 组件类
 */
class Component {

    /**
     * 组件
     * @param {Browser} browser 浏览器
     */
    constructor(browser = Browser.prototype) {
        this.browser = browser;
    }

    /**
     * 工厂方法，生成父组件的xpath
     * @returns 父组件的xpath
     */
    _createRootXpath() {
        return "";
    }

    /**
     * 工厂方法，生成组件的xpath
     * @returns 组件的xpath
     */
    _createXpath() {
        return "";
    }

    /**
     * 获取xpath
     * @returns xpath
     */
    getXpath() {
        return `${this._createRootXpath()}${this._createXpath()}`;
    }

    /**
     * 单击
     */
    async click() {
        try {
            await (await this.browser.findElement(this.getXpath())).click();
        } catch (error) {
            throw new Error(`单击失败: ${this.getXpath()}`);
        }
    }

    /**
     * 双击
     */
    async doubleClick() {
        try {
            await (await this.browser.findElement(this.getXpath())).doubleClick();
        } catch (error) {
            throw new Error(`双击失败: ${this.getXpath()}`);
        }
    }

    /**
     * 右击
     */
    async contextClick() {
        try {
            await (await this.browser.findElement(this.getXpath())).contextClick();
        } catch (error) {
            throw new Error(`右击失败: ${this.getXpath()}`);
        }
    }

    /**
     * 输入
     * @param  {...String} agrs 输入值
     */
    async input(...agrs) {
        try {
            await (await this.browser.findElement(this.getXpath())).input(...agrs);
        } catch (error) {
            throw new Error(`输入失败: ${this.getXpath()}`);
        }
    }

    /**
     * 清空
     */
    async clear() {
        try {
            await (await this.browser.findElement(this.getXpath())).clear();
        } catch (error) {
            throw new Error(`清空失败: ${this.getXpath()}`);
        }
    }

    /**
     * 获取文本
     * @returns 文本
     */
    async getText() {
        try {
            let text = await (await this.browser.findElement(this.getXpath())).getText(true);
            return text.trim();
        } catch (error) {
            throw new Error(`获取文本失败: ${this.getXpath()}`);
        }
    }

    /**
     * 获取属性值
     * @param  {String} attributeName 属性名
     * @returns 属性值
     */
    async getAttribute(attributeName) {
        try {
            let attribute = await (await this.browser.findElement(this.getXpath())).getAttribute(attributeName);
            return attribute && attribute.trim();
        } catch (error) {
            throw new Error(`获取属性值失败: ${this.getXpath()}`);
        }
    }

    /**
     * 获取value
     * @returns value
     */
    async getValue() {
        try {
            let value = await (await this.browser.findElement(this.getXpath())).getValue();
            return value.trim();
        } catch (error) {
            throw new Error(`获取value失败: ${this.getXpath()}`);
        }
    }

    /**
     * 等待组件显示
     */
    async waitUntilBeVisible() {
        try {
            await this.browser.waitUntilElementBeVisible(this.getXpath());
        } catch (error) {
            throw new Error(`等待组件显示失败: ${this.getXpath()}`);
        }
    }

    /**
     * 等待组件消失
     */
    async waitUntilBeNotVisible() {
        try {
            await this.browser.waitUntilElementBeNotVisible(this.getXpath());
        } catch (error) {
            throw new Error(`等待组件消失失败: ${this.getXpath()}`);
        }
    }

    /**
     * 等待组件不可用
     */
    async waitUntilBeDisabled() {
        try {
            let component = await this.browser.findElement(this.getXpath());
            await component.waitUntilBeDisabled();
        } catch (error) {
            throw new Error(`等待组件不可用失败: ${this.getXpath()}`);
        }
    }

    /**
     * 等待组件可用
     */
    async waitUntilBeEnabled() {
        try {
            let component = await this.browser.findElement(this.getXpath());
            await component.waitUntilBeEnabled();
        } catch (error) {
            throw new Error(`等待组件可用失败: ${this.getXpath()}`);
        }
    }

    /**
     * 判断组件是否显示
     * @param {Number} timeout 等待时间(ms)
     * @returns 是否显示
     */
    async isDisplayed(timeout = 200) {
        try {
            return await this.browser.isDisplayed(this.getXpath(), timeout);
        } catch (error) {
            throw new Error(`判断组件是否显示失败: ${this.getXpath()}`);
        }
    }

    /**
     * 判断组件是否选择
     * @returns 是否选择
     */
    async isSelected() {
        try {
            return await (await this.browser.findElement(this.getXpath())).isSelected();
        } catch (error) {
            throw new Error(`判断组件是否选择失败: ${this.getXpath()}`);
        }
    }

    /**
     * 判断组件是否可用
     * @returns 是否可用
     */
    async isEnabled() {
        try {
            return await (await this.browser.findElement(this.getXpath())).isEnabled();
        } catch (error) {
            throw new Error(`判断组件是否可用失败: ${this.getXpath()}`);
        }
    }

}

module.exports = Component;
